/*	Copyright (c) 2010 MIEM (http://miem.edu.ru/)
 *
 *	Authors:
 *		* Andrey Shtykovskiy    ( ashty@itas.miem.edu.ru      )
 *		* Edward Klyshinsky     ( klyshinsky@itas.miem.edu.ru )
 *		* Sergey R. Tumkovsky   ( srt@itas.miem.edu.ru        )
 *
 *	This file is part of MOAN (morphology analysis) software.
 *
 *	MOAN is free software: you can redistribute it and/or modify it 
 *	under the terms of the GNU General Public License as published 
 *	by the Free Software Foundation, either version 3 of the License, 
 *	or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License 
 *	along with MOAN. If not, see http://www.gnu.org/licenses/.
 */



#ifndef __BIT_RAKE_HPP_GUARD__
#define __BIT_RAKE_HPP_GUARD__

#include <assert.h>

namespace moan {

	template<typename _ty>
	class bit_rake {

	public:
		typedef _ty value_type;

		inline size_t cap() const {
			return _bit_cap;
		}

		inline void reset() {
			_value = 0;
		}

		inline void from_value(value_type v) {
			_value = v;
		}

		inline void	set(size_t bit_index) {
			_guard_bounds(bit_index);
			_value |= (value_type)1 << bit_index;
		}

		inline void	drop(size_t bit_index) {
			_guard_bounds(bit_index);
			_value &= ~( (value_type)1 << bit_index );
		}

		inline void	flip(size_t bit_index) {
			_guard_bounds(bit_index);
			_value ^= (value_type)1 << bit_index;
		}

		inline value_type extract(size_t bit_index) const {
			_guard_bounds(bit_index);
			return _value & ( (value_type)1 << bit_index );
		}

		inline value_type extract(
			size_t begin_bit_index, size_t end_bit_index) const {
			
			assert(begin_bit_index < end_bit_index);
			_guard_bounds(begin_bit_index);
			_guard_bounds(end_bit_index);

			value_type rv = 0;
			size_t current = begin_bit_index;
			size_t end = end_bit_index + 1;

			 for(;current != end; ++current) {
				 rv |= _value & ( (value_type)1 << current );
			 }

			 return rv;
		}

		bit_rake()
			: _value(0) { 			
				_bit_cap = _calculate_bit_cap();
		}

		explicit bit_rake(value_type new_value)
			: _value(new_value) { 
				_bit_cap = _calculate_bit_cap();
		}

		value_type value() const {
			return _value;
		}
		
	private:

		inline void _guard_bounds(size_t bit_index) const {
			assert( ( bit_index >= 0 ) && ( bit_index <= cap() ) );
		}

		inline size_t _calculate_bit_cap() const {
			return ( sizeof(value_type)*8 - 1 );
		}

		value_type _value;
		size_t _bit_cap;
	};
} /* namespace moan */

#endif /* __BIT_RAKE_HPP_GUARD__ */